package com.example.speedwaymanager;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;

import android.util.SparseArray;

final class PointsComparator implements Comparator<CRider> {
	@Override
	public int compare(CRider r1, CRider r2) {
		return r1.get_matchStats().get_points()
				.compareTo(r2.get_matchStats().get_points());
	}
}

public class CMatch {
	private ArrayList<CTeam> _teams;
	private ArrayList<CHeat> _heats = new ArrayList<CHeat>();
	private CSchedule _schedule;
	private final static int kMaxHeatCount = 15;
	private final static int kRaceGates = 4;
	private int _currentHeat = 0;
	private SparseArray<CRider> _rider = new SparseArray<CRider>();

	public CMatch(ArrayList<CTeam> teams, CSchedule schedule) {
		_teams = teams;		
		_schedule = schedule;
		teams.get(0).set_homeTeam(true);
		teams.get(1).set_homeTeam(false);
		for (CTeam team : teams) {
			if ( !team.is_isUser() || team.get_squad().isEmpty() )
				team.get_coach().createSquad();
			team.clearAllMatchPoints();
		}
		matchNoToRider();
		for (int i = 0; i < kMaxHeatCount - 2; ++i) {
			ArrayList<CRider> riders = new ArrayList<CRider>();
			for (int j = 0; j < kRaceGates; ++j) {
				int number = schedule.get_heat().get(i).get_gates().get(j)._no;
				CRider rider;
				if (number > 8) {
					rider = _teams.get(0).get_squad().get(number - 9);
					rider.set_matchAvg(rider.get_avgHome());
				} else {
					rider = _teams.get(1).get_squad().get(number - 1);
					rider.set_matchAvg(rider.get_avgAway());
				}
				rider.get_matchStats().set_number(number);
				riders.add(rider);
			}
			CHeat heat = new CHeat();
			heat.addRiders(riders);
			_heats.add(heat);
		}
	}

	private void matchNoToRider() {	
		for ( int number = 0; number < 7; ++number){
			_rider.put(number + 1, _teams.get(1).get_squad().get(number));
		}
		for ( int number = 0; number < 7; ++number){
			_rider.put(number + 9, _teams.get(0).get_squad().get(number));
		}
	}
	
	public Boolean isTacticalAllowedCPU() {
		int diff = _teams.get(0).get_points() - _teams.get(1).get_points();
		if (_currentHeat > 6 && _currentHeat < 15 && Math.abs(diff) > 5) // TODO to be parametrized 7
													// is for now
			return true;
		else
			return false;
	}
	
	public Boolean isTacticalAllowedUser() {
		int diff = _teams.get(0).get_points() - _teams.get(1).get_points();
		if (_currentHeat < 15 && Math.abs(diff) > 5) 
			return true;
		else
			return false;
	}

	private void replace(CRider rider1, CRider rider2) {
		rider1 = rider2;
		// TODO rider1._matchStats.addHeatPoints(0);
	}

	public CHeat peekNextHeat() {
		if ((_currentHeat + 1) <= kMaxHeatCount)
			return _heats.get(_currentHeat + 1);
		return null;
	}

	public void startNextHeat() {
		if ( _currentHeat < _heats.size() )
		{
			_heats.get(_currentHeat++).run();
			// assign team points after heat
			for (CTeam team : _teams) {
				team.calculateTeamPoints();
			}
			if ( _currentHeat == 13) {
				nominateToHeats14and15();
			}
			analyzeChangeRequest(_currentHeat);
		}		
	}

	public ArrayList<CRider> getHeatResults(int heat) {
		if (_heats.get(heat).get_RaceCompleted())
			return _heats.get(heat).get_riders();
		else
			return null;
	}

	public boolean isMatchCompleted() {
		boolean completed = true;
		for(CHeat heat:_heats) {
			if ( !heat.get_RaceCompleted() )
				completed = false; 
		}
		return completed;
	}
	/**
	 * Creates heat 14 and 15 using points. Best 2 riders from each team advance
	 * to 15th heat 3rd and 4th rider go to 14th heat.
	 */
	public void nominateToHeats14and15() {
		for (int i = 0; i < _teams.size(); ++i) {
			Collections
					.sort(_teams.get(i).get_riders(), new PointsComparator());
			Collections.reverse(_teams.get(i).get_riders());
		}
		nominateTo14();
		nominateTo15();
	}

	private void nominateTo14() {
		CHeat heat = new CHeat();
		ArrayList<CRider> riders = new ArrayList<CRider>();
		riders.add(_teams.get(1).get_riders().get(2)); // away 3rd		
		riders.add(_teams.get(0).get_riders().get(2)); // home 3rd
		riders.add(_teams.get(1).get_riders().get(3)); // away 4th
		riders.add(_teams.get(0).get_riders().get(3)); // home 4th
		heat.addRiders(riders);
		_heats.add(heat);
		_schedule.get_heat().get(13).get_gates().get(0)._no = riders.get(0).get_number();
		_schedule.get_heat().get(13).get_gates().get(1)._no = riders.get(1).get_number();
		_schedule.get_heat().get(13).get_gates().get(2)._no = riders.get(2).get_number();
		_schedule.get_heat().get(13).get_gates().get(3)._no = riders.get(3).get_number();
		
	}

	private void nominateTo15() {
		CHeat heat = new CHeat();
		ArrayList<CRider> riders = new ArrayList<CRider>();
		riders.add(_teams.get(0).get_riders().get(0)); // home 1st
		riders.add(_teams.get(1).get_riders().get(0)); // away 1st
		riders.add(_teams.get(0).get_riders().get(1)); // home 2nd
		riders.add(_teams.get(1).get_riders().get(1)); // away 2nd
		heat.addRiders(riders);
		_heats.add(heat);
		_schedule.get_heat().get(14).get_gates().get(0)._no = riders.get(0).get_number();
		_schedule.get_heat().get(14).get_gates().get(1)._no = riders.get(1).get_number();
		_schedule.get_heat().get(14).get_gates().get(2)._no = riders.get(2).get_number();
		_schedule.get_heat().get(14).get_gates().get(3)._no = riders.get(3).get_number();
	}

	public ArrayList<CRider> getRidersOfTeamInHeat(int heat, CTeam team) {
		return _heats.get(heat).get_ridersOfTeam(team);
	}

	/**
	 * @return the currentHeat
	 */
	public int getCurrentHeat() {
		return _currentHeat;
	}

	/**
	 * @return the currentHeat
	 */
	public int get_LastHeat() {
		if (_currentHeat <= 0)
			return _currentHeat;
		else
			return _currentHeat - 1;
	}

	/**
	 * @return the _heats
	 */
	public ArrayList<CHeat> get_heats() {
		return _heats;
	}

	public void analyzeChangeRequest(int i) {
		if (isTacticalAllowedCPU()) {
			if (_teams.get(0).get_points() < _teams.get(1).get_points()) {
				if ( !_teams.get(0).is_isUser() ) {
					_teams.get(0).get_coach().analyzeChangeRequest(i, this);
				}				
			} else {
				if ( !_teams.get(1).is_isUser() ) {
					_teams.get(1).get_coach().analyzeChangeRequest(i, this);
				}				
			}
		}
	}

	/**
	 * @return the _teams
	 */
	public ArrayList<CTeam> get_teams() {
		return _teams;
	}

	/**
	 * @return the _currentHeat
	 */
	public int get_currentHeat() {
		return _currentHeat;
	}

	/**
	 * @param _currentHeat the _currentHeat to set
	 */
	public void set_currentHeat(int _currentHeat) {
		this._currentHeat = _currentHeat;
	}

	/**
	 * @return the _schedule
	 */
	public CSchedule get_schedule() {
		return _schedule;
	}

	/**
	 * @return the _rider
	 */
	public SparseArray<CRider> get_rider() {
		return _rider;
	}

}
